<template>
  <el-form class="form" ref="formRef" :model="form" :rules="rules" :label-width="labelWidth">
    <el-form-item v-for="item in showConfigs" :key="item.key" :label="item.label" :prop="item.key"
      :label-width="item.labelWidth">
      <template v-if="item.type === 'input'">
        <el-input v-model="form[item.key]" v-bind="composeProps(item)" />
      </template>
      <template v-else-if="item.type === 'select'">
        <el-select v-model="form[item.key]" v-bind="composeProps(item)">
          <el-option v-for="option in item.options" :key="option[item.optionValueKey || 'value']"
            :label="option[item.optionLabelKey || 'label']" :value="option[item.optionValueKey || 'value']" />
        </el-select>
      </template>
      <template v-else-if="item.type === 'datepicker'">
        <el-date-picker v-model="form[item.key]" value-format="YYYY-MM-DD" v-bind="composeProps(item)" />
      </template>
      <template v-else-if="item.type === 'radio'">
        <el-radio-group v-model="form[item.key]" v-bind="composeProps(item)">
          <el-radio v-for="option in item.options" :key="option[item.optionValueKey || 'value']"
            :label="option[item.optionLabelKey || 'label']" :value="option[item.optionValueKey || 'value']" />
        </el-radio-group>
      </template>
      <template v-else-if="item.type === 'number'">
        <el-input-number v-model="form[item.key]" :controls="false" v-bind="composeProps(item)" />
        <div v-if="item.props?.showChinese" class="text-sm text-zinc-400 w-full mt-2">{{ number2text(form[item.key]) }}
        </div>
      </template>
      <template v-else-if="item.type === 'image'">
        <MyUpload v-bind="composeProps(item)" @change="onFileChange($event, item)"
          @upload="(url, file) => onUpload(url, file, item)" accept="image/*">
          <el-button v-if="!item.props?.disabled" type="primary">点击上传</el-button>
        </MyUpload>
        <div class="img-box w-full mt-4" v-if="item.props?.multiple">
          <el-image v-for="(img, imgI) in form[item.key]" class="w-24 h-24" fit="contain" :key="imgI"
            :src="img.url || img" :preview-src-list="form[item.key]"></el-image>
        </div>
        <div class="img-box w-full mt-4" v-else-if="form[item.key]">
          <el-image class="w-24 h-24" fit="contain" :src="form[item.key].url || form[item.key]"></el-image>
        </div>
      </template>
      <template v-else-if="item.type === 'file'">
        <MyUpload v-bind="composeProps(item)" @change="onFileChange($event, item)"
          @upload="(url, file) => onUpload(url, file, item)">
          <el-button v-if="!item.props?.disabled" type="primary">点击上传</el-button>
        </MyUpload>
        <template v-if="item.props?.multiple">
          <div class="flex items-center w-full mt-2" v-for="(file, fileI) in form[item.key]" :key="fileI">
            <el-icons class="w-4" name="Document" />
            <span class="mx-2 text-sm cursor-pointer" @click="onOpenFile(file)">{{ file.name || '点击查看' }}</span>
            <el-icons v-if="!item.props?.disabled" class="w-4 cursor-pointer hover:text-sky-400"
              @click="onDeleteFile(item, fileI)" name="CircleClose" />
          </div>
        </template>
        <div v-else-if="form[item.key]" class="flex items-center w-full mt-2">
          <el-icons class="w-4" name="Document" />
          <span class="mx-2 text-sm cursor-pointer" @click="onOpenFile(form[item.key])">{{ form[item.key].name || '点击查看'
            }}</span>
          <el-icons v-if="!item.props?.disabled" class="w-4 cursor-pointer hover:text-sky-400"
            @click="onDeleteFile(item)" name="CircleClose" />
        </div>
      </template>
      <template v-else-if="item.type === 'switch'">
        <el-switch v-model="form[item.key]" v-bind="composeProps(item)" />
      </template>
      <template v-else-if="item.type === 'custom'">
        <component :is="item.render" v-model="form[item.key]" v-bind="composeProps(item)"></component>
      </template>
    </el-form-item>
    <el-form-item>
      <el-button v-if="props.showSubmitBtn" type="primary" :loading="loading" @click="onSubmit()">确定</el-button>
      <el-button v-if="props.showCancelBtn" @click="onClose()">取消</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup>
import MyUpload from '@/components/MyUpload.vue'
import { ElMessage } from 'element-plus'
import { ref, reactive, computed } from 'vue'
import { number2text } from '@/utils/index'
const props = defineProps({
  info: Object,
  rawKey: String,
  server: Object,
  configs: {
    type: Array,
    required: true,
    default: () => [],
  },
  beforeSubmit: Function,
  showSubmitBtn: {
    type: Boolean,
    default: true,
  },
  showCancelBtn: {
    type: Boolean,
    default: true,
  },
})
const emit = defineEmits(['success', 'close'])

const form = reactive({})
const rules = {}
let maxLabelLength = 0
props.configs.forEach((cfg) => {
  form[cfg.key] = props.info?.[cfg.key] ?? cfg.defaultValue

  if (cfg.required) {
    if (cfg.rules) {
      rules[cfg.key] = cfg.rules
    } else {
      rules[cfg.key] = [{ required: true, message: '必填项', trigger: 'blur' }]
    }
  }

  maxLabelLength = Math.max(maxLabelLength, cfg.label.length)
})

const showConfigs = computed(() => {
  return props.configs.filter((cfg) => {
    return cfg.show ? cfg.show(form) : true
  })
})

// 合并普通props 和 动态props
const composeProps = (item) => {
  if (item.dynamicProps) {
    return {
      ...item.props,
      ...item.dynamicProps(form),
    }
  } else {
    return item.props;
  }
};

const labelWidth = maxLabelLength * 16 + 24 + 'px'

const onFileChange = (file, cfg) => {
  if (cfg.props?.multiple) {
    form[cfg.key] = (form[cfg.key] || []).concat(file)
    if (cfg.props.limitNumber && form[cfg.key].length > cfg.props.limitNumber) {
      form[cfg.key].length = cfg.props.limitNumber
    }
  } else {
    form[cfg.key] = file[0]
  }
}
const onDeleteFile = (cfg, index) => {
  if (cfg.props?.multiple) {
    form[cfg.key].splice(index, 1)
    if (form[cfg.key].length === 0) {
      form[cfg.key] = null
    }
  } else {
    form[cfg.key] = null
  }
}
const onUpload = (urlList, files, cfg) => {
  const fileObjs = urlList.map((url, i) => {
    return {
      url,
      name: files[i].name,
    }
  })
  if (cfg.props?.multiple) {
    form[cfg.key] = (form[cfg.key] || []).concat(fileObjs)
    if (cfg.props.limitNumber && form[cfg.key].length > cfg.props.limitNumber) {
      form[cfg.key].length = cfg.props.limitNumber
    }
  } else {
    form[cfg.key] = fileObjs[0]
  }
}

const formRef = ref()
const loading = ref(false)
const onSubmit = () => {
  formRef.value?.validate(async (valid) => {
    if (!valid) return
    loading.value = true
    try {
      let params = {}
      props.configs.forEach((cfg) => {
        params[cfg.key] = form[cfg.key]
        if (cfg.type === 'file') {
          if (Array.isArray(params[cfg.key])) {
            params[cfg.key] = params[cfg.key].map(file => file?.url || file)
          } else {
            params[cfg.key] = params[cfg.key]?.url || params[cfg.key]
          }
        }
      })
      if (props.beforeSubmit) {
        params = props.beforeSubmit(params)
      }
      console.log('params', params)
      if (props.info) {
        params[props.rawKey] = props.info[props.rawKey] || props.info.id
        const { data } = await props.server.put(params)
        emit('success', true, { params, result: data })
        ElMessage.success('修改成功')
      } else {
        const { data } = await props.server.post(params)
        emit('success', false, { params, result: data })
        ElMessage.success('添加成功')
      }
      onClose()
    } catch (e) {
      console.error(e)
    }
    loading.value = false
  })
}
const onClose = () => {
  emit('close')
}
const updateForm = (callback) => {
  const newForm = callback(form)
  Object.assign(form, newForm)
}

const onOpenFile = (file) => {
  if (file.url) {
    window.open(file.url, '_blank')
  }
}

defineExpose({
  updateForm,
})
</script>
